package mn.idax.exchange.otc.interceptor;

import com.alibaba.fastjson.JSON;
import mn.idax.exchange.auth.util.IpUtils;
import mn.idax.exchange.common.bean.ResponseData;
import mn.idax.exchange.otc.constant.Constant;
import mn.idax.exchange.otc.enums.ResponseEnum;
import mn.idax.exchange.otc.exception.IdaxException;
import mn.idax.exchange.otc.service.impl.MemoryService;
import mn.idax.exchange.otc.util.HttpHelper;
import mn.idax.exchange.otc.util.SignUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.DispatcherType;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * @program: open-api
 * @description: OtcSecurityInterceptor
 * @author: zhuwei
 * @create: 2020/07/22 14:33
 */
public class OtcSecurityInterceptor extends HandlerInterceptorAdapter {


    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(OtcSecurityInterceptor.class);
    protected static final String UTF_8 = "UTF-8";


    /**
     * @param httpServletRequest
     * @param httpServletResponse
     * @param o
     * @return boolean
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        String requestParam = null;
        try {
            /**获取请求参数 **/
            RequestWrapper requestWrapper = new RequestWrapper(httpServletRequest);
            requestParam = HttpHelper.getBodyString(requestWrapper);

            if (StringUtils.isEmpty(requestParam)) {
                LOGGER.error(JSON.toJSONString(ResponseData.error(ResponseEnum.PARAMETERS_NOT_EMPTY.getRespCode(), ResponseEnum.PARAMETERS_NOT_EMPTY.getRespMsg())));
                httpServletResponse.getOutputStream().write(JSON.toJSONString(ResponseData.error(ResponseEnum.PARAMETERS_NOT_EMPTY.getRespCode(), ResponseEnum.PARAMETERS_NOT_EMPTY.getRespMsg())).getBytes());
                return false;
            }
            Map paramMap = JSON.parseObject(requestParam);

            /**没带key**/
            if (!paramMap.containsKey(Constant.KEY)) {
                LOGGER.warn(JSON.toJSONString(ResponseData.error(ResponseEnum.KEY_DOES_NOT_EXIST.getRespCode(), ResponseEnum.KEY_DOES_NOT_EXIST.getRespMsg())));
                httpServletResponse.getOutputStream().write(JSON.toJSONString(ResponseData.error(ResponseEnum.KEY_DOES_NOT_EXIST.getRespCode(), ResponseEnum.KEY_DOES_NOT_EXIST.getRespMsg())).getBytes());
                return false;
            }
            /**没带时间戳**/
            if (!paramMap.containsKey(Constant.TIMESTAMP) || Long.valueOf(paramMap.get(Constant.TIMESTAMP).toString()) <= 0) {
                LOGGER.warn(JSON.toJSONString(ResponseData.error(ResponseEnum.NO_TIMESTAMP.getRespCode(), ResponseEnum.NO_TIMESTAMP.getRespMsg())));
                httpServletResponse.getOutputStream().write(JSON.toJSONString(ResponseData.error(ResponseEnum.NO_TIMESTAMP.getRespCode(), ResponseEnum.NO_TIMESTAMP.getRespMsg())).getBytes());
                return false;
            }
            /**没带签名**/
            if (!paramMap.containsKey(Constant.SIGN) || StringUtils.isEmpty(paramMap.get(Constant.SIGN).toString())) {
                LOGGER.warn(JSON.toJSONString(ResponseData.error(ResponseEnum.NO_SIGN.getRespCode(), ResponseEnum.NO_SIGN.getRespMsg())));
                httpServletResponse.getOutputStream().write(JSON.toJSONString(ResponseData.error(ResponseEnum.NO_SIGN.getRespCode(), ResponseEnum.NO_SIGN.getRespMsg())).getBytes());
                return false;
            }

            String apiKey = paramMap.get(Constant.KEY).toString();
            /**判断缓存中是否存在key**/
            Object systemApi = MemoryService.SYSTEMSETTINGMAP.get(apiKey);
            if (systemApi == null) {
                LOGGER.warn(JSON.toJSONString(ResponseData.error(ResponseEnum.KEY_DOES_NOT_EXIST.getRespCode(), ResponseEnum.KEY_DOES_NOT_EXIST.getRespMsg())));
                httpServletResponse.getOutputStream().write(JSON.toJSONString(ResponseData.error(ResponseEnum.KEY_DOES_NOT_EXIST.getRespCode(), ResponseEnum.KEY_DOES_NOT_EXIST.getRespMsg())).getBytes());
                return false;
            }

            /**添加异步判断***/
            if (!DispatcherType.ASYNC.equals(httpServletRequest.getDispatcherType())) {
//                LOGGER.info("OtcSecurityInterceptor=ip:{}requestParam{}",IpUtils.getIpAddr(httpServletRequest),requestParam);
                /**限流**/
//                ApiLimitUtils.apiLimit(identifier, apiUrl,  MemoryService.apiSignDefaultLimitMap.get(MemoryService.userMap.get(apikey.getUserid())));
                /**验证签名**/
                SignUtils.idaxApiVierfySign(paramMap);
            }

        } catch (IdaxException e) {
            LOGGER.warn("==Idax==OtcSecurityInterceptor=ip:{}requestParam{}", IpUtils.getIpAddr(httpServletRequest), requestParam + JSON.toJSONString(ResponseData.error(Integer.valueOf(e.getCode()), e.getMessage())));
            httpServletResponse.getOutputStream().write(JSON.toJSONString(ResponseData.error(Integer.valueOf(e.getCode()), e.getMessage())).getBytes());
            return false;
        } catch (Exception e) {
            LOGGER.warn("==OtcSecurityInterceptor===ip:{}requestParam{}", IpUtils.getIpAddr(httpServletRequest), requestParam + e.getMessage());
            httpServletResponse.getOutputStream().write(JSON.toJSONString(ResponseData.error(ResponseEnum.REQUEST_EXCEPTION.getRespCode(), ResponseEnum.REQUEST_EXCEPTION.getRespMsg())).getBytes());
            return false;
        }

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
    }
}
